﻿
using System;
using agsXMPP.protocol.client;
using sharpxbot.Core.Configuration;
using sharpxbot.Core.Connection;
using sharpxbot.Core.Messaging;
using sharpxbot.Core.Security.Traffic;
using sharpxbot.Core.Threading;
using sharpxbot.Plugins;
using sharpxbot.Plugins.Context;
using sharpxbot.Plugins.Loaders;
namespace sharpxbot.Core
{
    public class SharpXbot
    {
        public SharpXbot(IConfiguration configuration)
        {
            if (configuration == null)
                throw new NullReferenceException("Configuration can't be null");

            this.configuration = configuration;
            
        }

        /// <summary>
        /// Establishes connection with remote xmpp server using given configuration.
        /// This is async operation
        /// </summary>
        public void Connect()
        {
            IConnection connection = new ConnectionAdapter(configuration);
            connection.OnMessage += connection_OnMessage;
            connection.OnPresence += connection_OnPresence;
            connection.OnLogin += connection_OnLogin;

            connectionManager = new ConnectionManager(connection);
            ActiveHelper.StartIfActive(connectionManager);

            trafficRegistry = new TrafficRegistry(connection, configuration.TrafficLimit);
            trafficRegistry.OnLimitExceeded += traffic_OnLimitExceeded;
            ActiveHelper.StartIfActive(trafficRegistry);
        }

        void traffic_OnLimitExceeded(object sender, TrafficLimitExceededEventArgs e)
        {
            connectionManager.SuspendConnection(new TimeSpan(0, 15, 0));
        }

        void connection_OnPresence(object sender, Presence pres)
        {
            if (messageProcessor != null)
            {
                messageProcessor.ProcessMessage(new XmppMessage()
                {
                    Presence = pres
                });
            }
        }

        void connection_OnMessage(object sender, Message msg)
        {
            if (messageProcessor != null)
            {
                messageProcessor.ProcessMessage(new XmppMessage()
                {
                    Message = msg
                });
            }
        }

        void connection_OnLogin(object sender)
        {
            if (!isRunning) // bot is already running
            {
                pluginContext = new PluginContext(configuration, sender as IConnection);
                adminContext = new AdminContext(GetReportGenerator());
                messageProcessor = new PluginManager(new PluginLoader(pluginContext, adminContext), configuration.PluginsPath);

                isRunning = true;
            }
        }

        private ITrafficReportGenerator GetReportGenerator()
        {
            return trafficRegistry as ITrafficReportGenerator;
        }

        #region Private fields

        private IConfiguration configuration;
        private IPluginContext pluginContext;
        private IAdminContext adminContext;
        private IProcessor messageProcessor;

        private IConnectionManager connectionManager;
        private ITrafficRegistry trafficRegistry;

        private bool isRunning;

        #endregion
    }
}
